package com.whmnx.chitchat.utils;

import android.os.Message;
import android.util.Log;

import com.microsoft.signalr.Action1;
import com.microsoft.signalr.HubConnection;
import com.microsoft.signalr.HubConnectionBuilder;
import com.microsoft.signalr.HubConnectionState;
import com.microsoft.signalr.OnClosedCallback;
import com.orhanobut.logger.Logger;
import com.tencent.imsdk.TIMConversationType;
import com.whmnx.chitchat.bean.MessagePackBean;
import com.whmnx.chitchat.constants.Constants;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.UUID;

import io.reactivex.Single;

/**
 * 封装hubConnection
 * 1. 心跳机制
 * 2. 连接状态
 * 3. 监听收到的消息发送出去
 * 4. 开放开始连接，断开连接，发送消息三个方法
 * */
public class SignalRChannel {

    private final int ECHO_NUM      =  1001;
    private final int RECEIVE_NUM   =  1002;
    private final int KICKOUT_NUM   =  1003;
    private final int AUTH_NUM      =  1004;
    private final int CHECKAUTH_NUM =  1005;
    private final int OTHERCONNECTIONCHANGED_NUM = 1006;

    private String TAG = getClass().getSimpleName();
    private String url;
    private HubConnection hubConnection;

    private long heartDelay = 5*1000;
    private long KeepAliveTimeOutSecond = 5;
    private long lastRecvTime = 0;

    private boolean isRunning;
    private boolean connectStatus;

    public boolean isConnected() {
        return connectStatus;
    }

    private android.os.Handler receiveHandler;

    public SignalRChannel(String url1, android.os.Handler handler) {
        this.url = url1;
        this.receiveHandler = handler;
    }

    private void setOn(){
        //hubConnection关闭回调
        hubConnection.onClosed(new OnClosedCallback() {
            @Override
            public void invoke(Exception exception) {
                connectStatus = false;
                isRunning = false;
              //  reConnect();
            }
        });

        //与服务器交互，接收服务器的消息,ReceiveMsg为与服务器约定的方法，这里接收的是String，收到的消息
        hubConnection.on("broadcastMessage", new Action1<String>() {
            @Override
            public void invoke(String message) {//必须放在连接之前，方法名和后台约定的（子线程）
                //要展示接收到的消息一定要在主线程，不然会出现不显示等问题
                Logger.i("invoke----------------------");
                Logger.i(message.toString());
                Message msg = new Message();
                msg.obj = message;
                msg.what = ECHO_NUM;
                MessageReceived(msg);
            }
        }, String.class);

        //与服务器交互，接收服务器的消息,ReceiveMsg为与服务器约定的方法，这里接收的是String
        hubConnection.on("respMessage", new Action1<String>() {
            @Override
            public void invoke(String message) {//必须放在连接之前，方法名和后台约定的（子线程）
                //要展示接收到的消息一定要在主线程，不然会出现不显示等问题
                Logger.i("invoke----------------------");
                Logger.i(message.toString());
                Message msg = new Message();
                msg.obj = message;
                msg.what = RECEIVE_NUM;
                MessageReceived(msg);
            }
        }, String.class);
    }

    private void MessageReceived(Message msg){
        lastRecvTime = System.currentTimeMillis()/1000;
        //todo 传递给ReliableClient
        //使用handler
        Runnable receiverRun = new Runnable() {
            @Override
            public void run() {
                receiveHandler.sendMessage(msg);
            }
        };
        new Thread(receiverRun).start();
    }


    private void heartCheck(){
        Log.i(TAG,"wow this is heartCheck");
        new Thread(runnableHeart).start();
    }

    private Runnable runnableHeart = new Runnable() {
        @Override
        public void run() {
            while(isRunning){
                long ping = System.currentTimeMillis()/1000;
                //发送心跳包
                try{
                    if (isConnected()) {
                        MessagePackBean messagePackBean = new MessagePackBean();
                        UUID uuid = UUID.randomUUID();
                        messagePackBean.setID(uuid.toString());
                            messagePackBean.setReceiveId("123");
                            messagePackBean.setGroupID("");
                        messagePackBean.setType(0);
                        messagePackBean.setRecordType(0);

                        messagePackBean.setMessage("12");
                        messagePackBean.setSendId(SPUtil.getString(Constants.USERID));
                        hubConnection.send("SendMessage", messagePackBean);
                    }
                }catch (Exception e){
                    connectStatus = false;
                }
                //心跳延时
                try {
                    Thread.sleep(heartDelay);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //最后一次接收消息时间小于发送心跳时间，
                //起码在心跳时间内，没有收到包。
                if(lastRecvTime < ping){
                    long delay = System.currentTimeMillis()/1000 - ping;
                    //时间差大于重连时间的时候，判定为超时，连接状态置为false
                    if(delay > KeepAliveTimeOutSecond){
                        connectStatus = false;
                    }else {
                        connectStatus = true;
                    }
                }else {
                    connectStatus = true;
                }
            }
        }
    };

    /**
     * 开放的三个方法
     * */
    public void send(String method, Object... message){
        Log.i(TAG,"message:\n"+message+"   method"+method);
        try{
            hubConnection.send(method,message);
        }catch (Exception e){
            connectStatus = false;
        }

    }

    public void stopConnect(){
        isRunning = false;
        connectStatus = false;
        hubConnection.stop();
    }

    public void startConnect(){
        String token = SPUtil.getString(Constants.TOKEN);
        hubConnection = HubConnectionBuilder.create(Constants.CODEBUILD)
                .withAccessTokenProvider(Single.defer(() -> {
                    // Your logic here.
                    return Single.just(token);
                })).build();

        setOn();
        hubConnection.start().blockingAwait();
        heartCheck();
        connectStatus = true;
        isRunning = true;
    }


    /**
     * 检测是否连接
     */
    public  boolean isConnected2() {
        //这样判断并不准确
        if (hubConnection != null && hubConnection.getConnectionState() == HubConnectionState.CONNECTED)
            return true;
        return false;
    }
}
